using Microsoft.Extensions.Configuration;
using Volo.Abp.DependencyInjection;
using System;
using Matrix.Configuration;
using Matrix.Configuration.Services;

namespace Matrix.Configuration.Providers
{
    /// <summary>
    /// Matrix配置源
    /// </summary>
    public class MatrixConfigurationSource : IConfigurationSource, ITransientDependency
    {
        private readonly IServiceProvider _serviceProvider;

        public MatrixConfigurationSource(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        /// <summary>
        /// 构建配置提供者
        /// </summary>
        public IConfigurationProvider Build(IConfigurationBuilder builder)
        {
            // 从服务容器获取MatrixConfigurationProvider
            var existingProvider = _serviceProvider.GetService(typeof(MatrixConfigurationProvider)) as MatrixConfigurationProvider;
            if (existingProvider != null)
            {
                return existingProvider;
            }

            var configService = _serviceProvider.GetService(typeof(IConfigurationAppService)) as IConfigurationAppService;
            var clock = _serviceProvider.GetService(typeof(Volo.Abp.Timing.IClock)) as Volo.Abp.Timing.IClock;

            return new MatrixConfigurationProvider(configService!, clock!);
        }
    }

    /// <summary>
    /// Matrix配置扩展方法
    /// </summary>
    public static class MatrixConfigurationExtensions
    {
        /// <summary>
        /// 添加Matrix配置源
        /// </summary>
        public static IConfigurationBuilder AddMatrixConfiguration(this IConfigurationBuilder builder, IServiceProvider serviceProvider)
        {
            ArgumentNullException.ThrowIfNull(builder, nameof(builder));
            ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider));

            return builder.Add(new MatrixConfigurationSource(serviceProvider));
        }

        /// <summary>
        /// 添加Matrix配置源（异步版本）
        /// </summary>
        public static async Task<IConfigurationBuilder> AddMatrixConfigurationAsync(this IConfigurationBuilder builder, IServiceProvider serviceProvider)
        {
            ArgumentNullException.ThrowIfNull(builder, nameof(builder));
            ArgumentNullException.ThrowIfNull(serviceProvider, nameof(serviceProvider));

            var source = new MatrixConfigurationSource(serviceProvider);
            builder.Add(source);

            // 异步加载初始配置
            var provider = source.Build(builder) as MatrixConfigurationProvider;
            if (provider != null)
            {
                await provider.LoadAsync();
            }

            return builder;
        }
    }
}